package com.fizzkai.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.keygen.DefaultKeyGenerator;
import com.dangdang.ddframe.rdb.sharding.keygen.KeyGenerator;
import com.fizzkai.common.ModuleDatabaseShardingAlgorithm;
import com.mysql.jdbc.Driver;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName DataSourceConfiguration
 * @Description TODO
 * @Author weijh3
 * @Date 2018/11/26 下午6:45
 * @Version 1.0
 **/
@Configuration
public class DataSourceConfiguration {

    @Value("${datasourcemap.db0.name}")
    private String db0Name;

    @Value("${datasourcemap.db0.host}")
    private String db0Host;

    @Value("${datasourcemap.db0.port}")
    private String db0Post;

    @Value("${datasourcemap.db0.user}")
    private String db0User;

    @Value("${datasourcemap.db0.pass}")
    private String db0Pass;

    @Value("${datasourcemap.db1.name}")
    private String db1Name;

    @Value("${datasourcemap.db1.host}")
    private String db1Host;

    @Value("${datasourcemap.db1.port}")
    private String db1Post;

    @Value("${datasourcemap.db1.user}")
    private String db1User;

    @Value("${datasourcemap.db1.pass}")
    private String db1Pass;

    @Bean
    public DataSource getDataSource() throws SQLException {
        return buildDataSource();
    }

    private DataSource buildDataSource() throws SQLException {
        // 设置分库映射 自定义一个Map , 名字随意
        Map<String, DataSource> dataSourceMap = new HashMap<>(2);
        // 添加两个数据库db0,db1到map里
        // key 是关键
        dataSourceMap.put("db0", createDataSource(db0Name, db0Host, db0Post, db0User, db0Pass));
        dataSourceMap.put("db1", createDataSource(db1Name, db1Host, db1Post, db1User, db1Pass));
        // 设置默认db为db0，也就是为那些没有配置分库分表策略的指定的默认库
        // 如果只有一个库，也就是不需要分库的话，map里只放一个映射就行了，只有一个库时不需要指定默认库，但2个及以上时必须指定默认库，否则那些没有配置策略的表将无法操作数据
        DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap, "db0");

        // 创建一个 表，绑定 datasource
        TableRule orderTableRule = TableRule.builder("user")
                .dataSourceRule(dataSourceRule)
                .build();

        // 具体分库分表策略，按什么规则来分
        // nuid Long 类型, 哪个字段 哪个规则
        DatabaseShardingStrategy nuid = new DatabaseShardingStrategy("nuid", new ModuleDatabaseShardingAlgorithm());
        ShardingRule shardingRule = ShardingRule.builder()
                .dataSourceRule(dataSourceRule)
                .tableRules(Arrays.asList(orderTableRule))
                .databaseShardingStrategy(nuid)
                .build();

        DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);

        return dataSource;
    }

    /**
     * 创建 自己 datasource
     * @param dbName
     * @param dbHost
     * @param dbPost
     * @param dbUser
     * @param dbPass
     * @return
     */
    private static DataSource createDataSource(String dbName, String dbHost, String dbPost, String dbUser, String dbPass) {
        // 使用druid连接数据库
        DruidDataSource result = new DruidDataSource();
        result.setDriverClassName(Driver.class.getName());
        result.setUrl(String.format("jdbc:mysql://%s:%s/%s", dbHost, dbPost, dbName));
        result.setUsername(dbUser);
        result.setPassword(dbPass);
        return result;
    }

    @Bean
    public KeyGenerator keyGenerator() {
        return new DefaultKeyGenerator();
    }
}
